﻿namespace MefContrib.Models.Provider.Definitions.Fluent
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq.Expressions;
    
    /// <summary>
    /// 
    /// </summary>
    public class FluentDefinitionProvider : DefinitionProvider
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FluentDefinitionProvider"/> class.
        /// </summary>
        public FluentDefinitionProvider()
        { 
            this.Descriptions = new Collection<PartDescription>();
        }

        /// <summary>
        /// Gets a list of the <see cref="PartDescription"/> objected which is known by the provider.
        /// </summary>
        /// <value>A <see cref="List{T}"/> collection, containing <see cref="PartDescription"/> objects.</value>
        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "The property can be assigned in derived classes.")]
        public Collection<PartDescription> Descriptions { get; protected set; }

        /// <summary>
        /// Gets a list of the <see cref="PartDescription"/> objected which is known by the provider.
        /// </summary>
        /// <value>A <see cref="IEnumerable{T}"/> collection, containing <see cref="PartDescription"/> objects.</value>
        public override IEnumerable<PartDescription> Parts
        {
            [DebuggerStepThrough]
            get { return this.Descriptions; }
        }

        /// <summary>
        /// Registers an export with no return value.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> that the export is registered for.</typeparam>
        /// <returns>A <see cref="ExportDecorator"/> object.</returns>
        /// <remarks>This overload handles methods with no return (void) value.</remarks>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "The lambda expression is required to identify the export.")]
        public ExportDecorator Export<T>()
        {
            var decorator =
                new ExportDecorator(this);
            return decorator.Export<T>();
        }

        /// <summary>
        /// Registers an export with no return value.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> that the export is registered for.</typeparam>
        /// <param name="exportExpression">A lambda expression used to identify the export.</param>
        /// <returns>A <see cref="ExportDecorator"/> object.</returns>
        /// <remarks>This overload handles methods with no return (void) value.</remarks>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "The lambda expression is required to identify the export.")]
        public ExportDecorator Export<T>(Expression<Action<T>> exportExpression)
        {
            var decorator =
                new ExportDecorator(this);
            return decorator.Export<T>(exportExpression);
        }

        /// <summary>
        /// Registers an export with a return value.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> that the export is being registered for.</typeparam>
        /// <param name="exportExpression">A lambda expression used to identify the export.</param>
        /// <returns>A <see cref="ExportDecorator"/> object.</returns>
        /// <remarks>This overload handled properties, fields, methods with a return value and classes.</remarks>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "The lambda expression is required to identify the export.")]
        public ExportDecorator Export<T>(Expression<Func<T, object>> exportExpression)
        {
            var decorator =
                new ExportDecorator(this);
            return decorator.Export(exportExpression);
        }

        /// <summary>
        /// Registers an import.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> that the import is being registered for.</typeparam>
        /// <param name="importExpression">A lambda expression used to identify the import.</param>
        /// <returns>A <see cref="ImportDecorator"/></returns> object.
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "The lambda expression is required to identify the import.")]
        public ImportDecorator Import<T>(Expression<Func<T, object>> importExpression)
        {
            var decorator =
                new ImportDecorator(this);
            return decorator.Import(importExpression);
        }
    }
}
